package chen.web.controller.forum.model;

import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import chen.web.MyContextProvider;
import chen.web.antispam.Characteristic;
import chen.web.antispam.Judge;
import chen.web.antispam.JudgeStore;
import chen.web.cache.CacheUtils;
import chen.web.config.ConfigRepository;
import chen.web.config.SiteConfig;
import chen.web.controller.UbbParserFactory;
import chen.web.stat.StatisticsFilter;
import chen.web.util.Birthday;
import chen.web.util.ContentFilter;
import chen.web.util.IpUtil;
import chen.web.util.PathUtil;
import chen.web.util.SubString;

@Component
public class Utils {

	@Autowired 
	private JudgeStore judgeFactory;
	
	public String dateFormat(Date date){
		if(date == null) return "";
		Calendar today = Calendar.getInstance();
		today.set(Calendar.HOUR_OF_DAY, 0);
		today.set(Calendar.MINUTE, 0);
		today.set(Calendar.SECOND, 0);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		if(calendar.before(today)){
			return calendar.get(Calendar.MONTH) + 1 + "-" + calendar.get(Calendar.DATE);
		}
		return calendar.get(Calendar.HOUR_OF_DAY )+ ":" + calendar.get(Calendar.MINUTE);
	}
	
	public String dateFormat(String partten, Date date){
		if(date == null) return "";
		SimpleDateFormat format = new SimpleDateFormat(partten);
		return format.format(date);
	}
	
	public String dateFormat(String partten, Long date){
		if(date == null) return "";
		SimpleDateFormat format = new SimpleDateFormat(partten);
		return format.format(new Date(date));
	}
	
	public String ipFormat(String ip){
		return IpUtil.format(ip);
	}
	
	public String description(final String content, int maxLength){
		String str = ContentFilter.removeHtml(content);
		String temp = str.replaceAll("&nbsp;", " ");
		temp = temp.replaceAll("\"", "&quot;");
		char[] charArray = new char[maxLength];
		int count = 0;
		boolean separator = false;
		for(int i=0; i<temp.length() && count<maxLength; i++){
			char ch = temp.charAt(i);
			if(ch=='\n' || ch=='\t' || ch=='\r' || ch==' ' || ch=='　'){
				if(separator == false){
					charArray[count] = ' ';
					++ count;
				}
				separator = true;
				continue;
			} 
			if(ch<128 && (ch=='!' || ch=='.' || ch==',' || ch==';' || ch=='?' || ch==':' || ch=='"')){
				separator = true;
			} else if(ch=='！' || ch=='，' || ch=='．' || ch=='。' || ch=='；' || ch=='？' || ch=='：'){
				separator = true;
			} else {
				separator = false;	
			}
			charArray[count] = ch;
			++ count;
		}
		String result = SubString.subString(String.copyValueOf(charArray, 0, count), maxLength);
		if(result.length() < count){
			result = result + " ...";
		}
		return result.replaceAll("\"", "&quot;");
	}
	
	private Timer timer = new Timer();
	public Timer getTimer(){
		return timer;
	}
	
	
	
	private static Cache AllInOneUrlCache;
	static{
		CacheConfiguration config = new CacheConfiguration("AllInOneUrlCache", Integer.MAX_VALUE)
									.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.FIFO)
									.eternal(false)
									.diskPersistent(false);
		AllInOneUrlCache = new Cache(config);
		CacheManager.create().addCache(AllInOneUrlCache);
		CacheUtils.storeDescription(AllInOneUrlCache, "缓存allInOne静态文件的url");
	}
	
	public String allInOne(String ...filePaths) throws NoSuchAlgorithmException, IOException{
		StringBuilder key = new StringBuilder();
		for(String path : filePaths){
			key.append(path);
		}
		Element elem = AllInOneUrlCache.get(key.toString());
		if(elem != null){
			return (String)elem.getValue();
		}
		String allInOneUrl = generateUrl(filePaths);
		Element element = new Element(key.toString(), allInOneUrl);
		AllInOneUrlCache.put(element);
		return allInOneUrl;
	}
	
	private synchronized String generateUrl(String ...filePaths) throws IOException, NoSuchAlgorithmException{
		String appPath = PathUtil.getAppDirectory().getPath();
		CharArrayWriter writer = new CharArrayWriter();
		File directory = null;
		for(String path : filePaths){
			String absolotePath = appPath + path.replace('/', File.separatorChar);
			if(directory == null){
				directory = new File(absolotePath).getParentFile();
			}
			FileInputStream fis = new FileInputStream(absolotePath);
			InputStreamReader reader = new InputStreamReader(fis, "UTF-8");
			for(int ch=reader.read(); ch!=-1; ch=reader.read()){
				writer.write(ch);
			}
			reader.close();
			fis.close();
		}
		
		StringBuffer cacheFilePath = new StringBuffer();
		cacheFilePath.append(directory.getAbsolutePath())
					.append(File.separatorChar)
					.append("cache_")
					.append(md5(filePaths))
					.append('.')
					.append(suffix(filePaths));
		
		File file = new File(cacheFilePath.toString());
		file.getParentFile().mkdirs();
		FileOutputStream fos = new FileOutputStream(file);
		OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
		osw.write(writer.toCharArray());
		writer.close();
		osw.close();
		
		String relative = cacheFilePath.toString().substring(appPath.length()).replace(File.separatorChar, '/');
		StringBuffer result = new StringBuffer();
		result.append(ConfigRepository.instance().get(SiteConfig.class).getBaseURL())
				.append(relative)
				.append('?');
		for(String path : filePaths){
			result.append(path).append("_");
		}
		result.append(System.currentTimeMillis());
		
		return result.toString();
	}
	
	public Birthday birthday(Date date){
		Birthday birthday = new Birthday(date);
		return birthday;
	}
	
	public String percent(float f){
		NumberFormat format = NumberFormat.getPercentInstance();
		return format.format(f);
	}
	
	public Header getHeader(){
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		return new Header(request);
	}
	
	public int getStatId(){
		Integer id = (Integer)MyContextProvider.getMyContext().getAttribute(StatisticsFilter.StatIdAttributeName);
		if(id == null){
			return 0;
		}
		return id;
	}
	
	private String md5(String ...filePaths) throws NoSuchAlgorithmException, UnsupportedEncodingException{
		MessageDigest md = MessageDigest.getInstance("MD5");
		for(String path : filePaths){
			md.update(path.getBytes("UTF-8"));
		}
		byte[] digest = md.digest();
		StringBuffer hexString = new StringBuffer();
		for(int i=0; i<digest.length; i++){
			hexString.append(Integer.toHexString((0x000000ff & digest[i]) | 0xffffff00).substring(6));
		}
		return hexString.toString();
	}
	
	
	private String suffix(String ...filePaths){
		String suffix = null;
		for(String path : filePaths){
			int i = path.lastIndexOf('.');
			if(i!=-1 && i!=path.length()-1){
				String str = path.substring(i+1);
				if(!"js".equalsIgnoreCase(str) && !"css".equalsIgnoreCase(str))
					throw new IllegalArgumentException("只接受js和css后缀");
				if(suffix == null)
					suffix = str;
				if(!suffix.equalsIgnoreCase(str))
					throw new IllegalArgumentException("后缀名不一致");
			}else {
				throw new IllegalArgumentException("没有后缀名");
			}
		}
		return suffix;
	}
	
	public String ubb2html(String ubb){
		return UbbParserFactory.standard().parse(ubb).toHtml();
	}
    
    private boolean isLetter(char c) {
        int k = 0x80;
        return c / k == 0 ? true : false;
    }
	
    private String subString(String str, int width){
    	if(str == null){
    		return "";
    	}
    	if(width <= 0){
    		throw new IllegalArgumentException();
    	}
    	if(str.length() < width/2){
    		return str;
    	}
    	int length = 0;
    	int index = -1;
    	for(int i=0; i<str.length(); i++){
    		char ch = str.charAt(i);
    		++ length;
    		if(!isLetter(ch)){
    			++ length;
    		}
     		if(length > width){
    			index = i;
    			break;
    		}
    	}
    	if(index == -1){
    		return str;
    	} else{
    		return str.substring(0,index);	
    	}
    }
    
    public String ellipsis(String str, int width){
    	String s = subString(str, width);
    	if(str.length() != s.length()){
    		return s + " ...";
    	}
    	return s;
    }
    
    public boolean judge(String action){
    	Judge judge = judgeFactory.getJudge(action);
    	//默认是false
    	if(judge == null){
    		return false;
    	}
    	return judge.against(Characteristic.newInstance());  		
    }
}
